package com.yy.ttmodule.udp;


import android.support.annotation.NonNull;
import android.util.Log;

import com.yy.ttmodule.control.Constant;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Arrays;

public final class UdpRxDataTask implements Runnable {

    private final String TAG = "RxDataThread";

    private final byte IDLE_BEGIN = 0;
    private final byte HEADER_DATA = 1;

    private byte c_state = IDLE_BEGIN;
    private short offset;

    private DatagramSocket socket;

    private byte[] buff = new byte[UdpCommand.RECEIVE_PACK_LEN_MAX];
    private int iDataLen;

    private byte[] readDataBuffer = new byte[UdpCommand.RECEIVE_PACK_LEN_MAX];
    private int rawPackageLen;
    private byte[] ResultBuf = new byte[UdpCommand.RECEIVE_PACK_LEN_MAX];

    private int cacheLen = 0;
    private byte cacheByte[] = new byte[UdpCommand.RECEIVE_PACK_LEN_MAX * 8];

    private int frameLenVal = 0;
    private int pkgHeadPos = 0;
    private int pkgEndPos = 0;

    public UdpRxDataTask(@NonNull DatagramSocket socket) {
        this.socket = socket;
    }

    private synchronized void reSet() {
        c_state = IDLE_BEGIN;
        offset = 0;
        frameLenVal = 0;
        pkgHeadPos = 0;
    }

    public static final int MTU = 512 * 1024;
    private byte mReceiveBuffer[] = new byte[MTU];

    @Override
    public void run() {
        try {
            DatagramPacket packet = new DatagramPacket(mReceiveBuffer, MTU);

            while (UdpServer.isReadData
                    && null != socket && !socket.isClosed()) {

                pkgEndPos = 0;

                //接收数据
                socket.receive(packet);
                Constant.CLIENT_IP = packet.getAddress().getHostAddress();
                Log.d(TAG, "receive Package ip >>  " + Constant.CLIENT_IP);
                buff = packet.getData();
//                buff = new byte[] { (byte) 0xAA, 0x60, (byte) 0xAA, 0x60, 0x01, 0x00, 0x01, 0x0, 0x06, (byte) 0xE4, };
//                buff = new byte[] { (byte) 0xAA, 0x60, (byte) 0xAA, 0x60, 0x01, 0x00, 0x01, 0x0, };

                buff = packet.getData();
                if (buff == null || packet.getLength() == 0) {
                    Thread.sleep(100);
                    continue;
                }
                iDataLen = packet.getLength();
                Log.d(TAG, "receive Package >>  " + ConvertData.byteArrayToHexString(buff, iDataLen));

                //拷贝读取数据到缓存中
                System.arraycopy(buff, 0, cacheByte, cacheLen, iDataLen);
                cacheLen += iDataLen;

                //设置包头
                byte[] PACK_FRAME_HEADER = UdpCommand.PACK_FRAME_HEADER;
                if ( cacheLen < PACK_FRAME_HEADER.length ) {
                    Thread.sleep(100);
                    continue;
                }

                //找数据包
                for (int i = 0; i < cacheLen; i++) {
                    switch (c_state) {
                        case IDLE_BEGIN:
                            //找包头
                            if ( (cacheLen - i) < PACK_FRAME_HEADER.length ) {
                                break;
                            }
                            if ( cacheByte[i] == PACK_FRAME_HEADER[0] &&
                                    cacheByte[i + 1] == PACK_FRAME_HEADER[1] &&
                                    cacheByte[i + 2] == PACK_FRAME_HEADER[2] &&
                                    cacheByte[i + 3] == PACK_FRAME_HEADER[3] ) {

                                //buff剩余长度小于 数据包帧长度之前的长度
                                if ( (cacheLen - i) < UdpCommand.RECEIVE_FRAME_LEN_POS ) {
                                    break;
                                }

                                frameLenVal = DataTypeConversion.bytesToShortLiterEnd(cacheByte,
                                        i + UdpCommand.RECEIVE_PACK_HEAD_LEN + UdpCommand.RECEIVE_PACK_PARAM_LEN);

                                Log.d(TAG,"IDLE_BEGIN = " + i);
                                //buff剩余长度小于 数据包长度
                                if ( (cacheLen - i) < (frameLenVal + UdpCommand.RECEIVE_PACK_EXC_FRAME_LEN) ) {
                                    break;
                                }
                                pkgHeadPos = i;

                                readDataBuffer[offset] = buff[i];
                                readDataBuffer[offset++] = buff[i++];
                                readDataBuffer[offset++] = buff[i++];
                                readDataBuffer[offset++] = buff[i];
                                c_state = HEADER_DATA;
                            }
                            break;
                        case HEADER_DATA:
                            //找包尾
                            if (offset > UdpCommand.RECEIVE_PACK_LEN_MAX) {
                                reSet();
                                break;
                            }

                            readDataBuffer[offset] = buff[i];
                            offset++;

                            //i-pkgHeadPos+1包长度，是否等于帧长度加上其他部分长度
                            if ( (frameLenVal + UdpCommand.RECEIVE_PACK_EXC_FRAME_LEN)
                                    == (i - pkgHeadPos + 1) ) {
                                rawPackageLen = UdpDataUtil.comUnPackage(readDataBuffer, ResultBuf, offset);
                                if (rawPackageLen > 0) {
                                    reSet();
                                    //找到包尾在缓存内位置
                                    pkgEndPos = i + 1;
                                    UdpRxData.getInstance().rxDataPackage(ResultBuf, rawPackageLen);
                                    Log.d(TAG,"rxDataPackage byte = " +
                                            ConvertData.byteArrayToHexString(ResultBuf, rawPackageLen));
                                }
                            }
                            break;
                    }
                }

                if ( pkgEndPos > 0 ) {
                    byte[] tmpBuffer = new byte[UdpCommand.RECEIVE_PACK_LEN_MAX * 8];
                    cacheLen = cacheLen - pkgEndPos;
                    //缓存用完
                    if ( cacheLen == 0 ) {
                        Arrays.fill(cacheByte, (byte)0x00);
                    } else {
                        //提取数据包后，从包尾在缓存位置下一位，到缓存最后，拷贝到新缓存内
                        System.arraycopy(cacheByte, pkgEndPos, tmpBuffer, 0, cacheLen);
                        System.arraycopy(tmpBuffer, 0, cacheByte, 0, cacheLen);
                    }
                    Log.d(TAG,"cache Byte = " +
                            ConvertData.byteArrayToHexString(cacheByte, cacheLen));
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
